﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Windows.Forms

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class DynamicActionMessageFilter
        Inherits WorkflowDesignerMessageFilter
        ' Methods
        Friend Sub New()
        End Sub

        Friend Function ActionExists(ByVal action As DynamicAction) As Boolean
            If (action Is Nothing) Then
                Throw New ArgumentNullException("action")
            End If
            Return Me.actions.Contains(action)
        End Function

        Friend Sub AddAction(ByVal action As DynamicAction)
            If (action Is Nothing) Then
                Throw New ArgumentNullException("action")
            End If
            If Not Me.actions.Contains(action) Then
                If Me.IsButtonDragged Then
                    Me.SetDraggedButton(-1, -1)
                End If
                Me.actions.Add(action)
                Me.RefreshAction(action)
            End If
        End Sub

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            Try 
                Dim service As IServiceContainer = [TryCast](MyBase.GetService(GetType(IServiceContainer)),IServiceContainer)
                If (Not service Is Nothing) Then
                    service.RemoveService(GetType(DynamicActionMessageFilter))
                End If
            Finally
                MyBase.Dispose(disposing)
            End Try
        End Sub

        Private Function GetActionBounds(ByVal actionIndex As Integer) As Rectangle
            Dim destination As New Rectangle(Point.Empty, MyBase.ParentView.ViewPortSize)
            Dim action As DynamicAction = Me.actions.Item(actionIndex)
            destination.Inflate(-action.DockMargin.Width, -action.DockMargin.Height)
            Return New Rectangle(ActivityDesignerPaint.GetRectangleFromAlignment(action.DockAlignment, destination, action.Bounds.Size).Location, action.Bounds.Size)
        End Function

        Private Function GetButtonBounds(ByVal actionIndex As Integer, ByVal buttonIndex As Integer) As Rectangle
            Dim actionBounds As Rectangle = Me.GetActionBounds(actionIndex)
            Dim buttonBounds As Rectangle = Me.actions.Item(actionIndex).GetButtonBounds(buttonIndex)
            buttonBounds.Offset(actionBounds.Location)
            Return buttonBounds
        End Function

        Protected Overrides Sub Initialize(ByVal parentView As WorkflowView)
            MyBase.Initialize(parentView)
            Dim service As IServiceContainer = [TryCast](MyBase.GetService(GetType(IServiceContainer)),IServiceContainer)
            If (Not service Is Nothing) Then
                service.RemoveService(GetType(DynamicActionMessageFilter))
                service.AddService(GetType(DynamicActionMessageFilter), Me)
            End If
        End Sub

        Protected Overrides Function OnMouseCaptureChanged() As Boolean
            If Me.IsButtonDragged Then
                Me.SetDraggedButton(-1, -1)
            End If
            Return False
        End Function

        Protected Overrides Function OnMouseDoubleClick(ByVal eventArgs As MouseEventArgs) As Boolean
            Dim i As Integer = (Me.actions.Count - 1)
            Do While (i >= 0)
                Dim local1 As DynamicAction = Me.actions.Item(i)
                If Me.GetActionBounds(i).Contains(New Point(eventArgs.X, eventArgs.Y)) Then
                    Return True
                End If
                i -= 1
            Loop
            Return False
        End Function

        Protected Overrides Function OnMouseDown(ByVal eventArgs As MouseEventArgs) As Boolean
            Dim point As New Point(eventArgs.X, eventArgs.Y)
            Me.Refresh
            Me.UpdateTransparency(point)
            Dim flag As Boolean = False
            If ((eventArgs.Button And MouseButtons.Left) > MouseButtons.None) Then
                Dim i As Integer = (Me.actions.Count - 1)
                Do While (i >= 0)
                    Dim action As DynamicAction = Me.actions.Item(i)
                    If Me.GetActionBounds(i).Contains(point) Then
                        Dim j As Integer
                        For j = 0 To action.Buttons.Count - 1
                            If (Me.GetButtonBounds(i, j).Contains(point) AndAlso (action.Buttons.Item(j).State = States.Disabled)) Then
                                Return True
                            End If
                        Next j
                        Dim k As Integer
                        For k = 0 To action.Buttons.Count - 1
                            Dim button As ActionButton = action.Buttons.Item(k)
                            If (button.State <> States.Disabled) Then
                                If Me.GetButtonBounds(i, k).Contains(point) Then
                                    button.State = States.Pressed
                                    If (action.ActionType <> ActionTypes.TwoState) Then
                                        Me.SetDraggedButton(i, k)
                                    End If
                                ElseIf (action.ActionType = ActionTypes.TwoState) Then
                                    button.State = States.Normal
                                End If
                            End If
                        Next k
                        flag = True
                    End If
                    i -= 1
                Loop
            End If
            Return flag
        End Function

        Protected Overrides Function OnMouseEnter(ByVal eventArgs As MouseEventArgs) As Boolean
            Me.UpdateTransparency(New Point(eventArgs.X, eventArgs.Y))
            Me.Refresh
            Return False
        End Function

        Protected Overrides Function OnMouseLeave() As Boolean
            MyBase.ParentView.ShowInfoTip(String.Empty)
            Me.UpdateTransparency(Point.Empty)
            Me.Refresh
            Return False
        End Function

        Protected Overrides Function OnMouseMove(ByVal eventArgs As MouseEventArgs) As Boolean
            Dim point As New Point(eventArgs.X, eventArgs.Y)
            Me.Refresh
            Me.UpdateTransparency(point)
            Dim text As String = String.Empty
            Dim isButtonDragged As Boolean = Me.IsButtonDragged
            If Not Me.IsButtonDragged Then
                Dim i As Integer = (Me.actions.Count - 1)
                Do While (i >= 0)
                    Dim action As DynamicAction = Me.actions.Item(i)
                    Dim actionBounds As Rectangle = Me.GetActionBounds(i)
                    Dim j As Integer
                    For j = 0 To action.Buttons.Count - 1
                        Dim button As ActionButton = action.Buttons.Item(j)
                        If actionBounds.Contains(point) Then
                            Dim flag2 As Boolean = Me.GetButtonBounds(i, j).Contains(point)
                            If (flag2 AndAlso ([text].Length = 0)) Then
                                [text] = button.Description
                            End If
                            If ((button.State <> States.Disabled) AndAlso (button.State <> States.Pressed)) Then
                                If flag2 Then
                                    button.State = States.Highlight
                                Else
                                    button.State = States.Normal
                                End If
                            End If
                            isButtonDragged = True
                        ElseIf (button.State = States.Highlight) Then
                            button.State = States.Normal
                        End If
                    Next j
                    i -= 1
                Loop
            End If
            Dim parentView As WorkflowView = MyBase.ParentView
            If ([text].Length > 0) Then
                Me.infoTipSet = True
                parentView.ShowInfoTip([text])
                Return isButtonDragged
            End If
            If Me.infoTipSet Then
                parentView.ShowInfoTip(String.Empty)
                Me.infoTipSet = False
            End If
            Return isButtonDragged
        End Function

        Protected Overrides Function OnMouseUp(ByVal eventArgs As MouseEventArgs) As Boolean
            Dim point As New Point(eventArgs.X, eventArgs.Y)
            Me.Refresh
            Me.UpdateTransparency(point)
            Dim flag As Boolean = False
            If ((eventArgs.Button And MouseButtons.Left) > MouseButtons.None) Then
                Dim i As Integer = (Me.actions.Count - 1)
                Do While (i >= 0)
                    Dim action As DynamicAction = Me.actions.Item(i)
                    If Me.GetActionBounds(i).Contains(point) Then
                        Dim j As Integer
                        For j = 0 To action.Buttons.Count - 1
                            Dim button As ActionButton = action.Buttons.Item(j)
                            If (button.State <> States.Disabled) Then
                                If (Me.GetButtonBounds(i, j).Contains(point) AndAlso (action.ActionType <> ActionTypes.TwoState)) Then
                                    button.State = States.Highlight
                                ElseIf (button.State = States.Highlight) Then
                                    button.State = States.Normal
                                End If
                            End If
                        Next j
                        flag = True
                    End If
                    i -= 1
                Loop
            End If
            If Me.IsButtonDragged Then
                Me.SetDraggedButton(-1, -1)
            End If
            Return flag
        End Function

        Protected Overrides Function OnPaintWorkflowAdornments(ByVal e As PaintEventArgs, ByVal viewPort As Rectangle, ByVal ambientTheme As AmbientTheme) As Boolean
            Dim i As Integer
            For i = 0 To Me.actions.Count - 1
                Dim container As GraphicsContainer = e.Graphics.BeginContainer
                Dim location As Point = Me.GetActionBounds(i).Location
                e.Graphics.TranslateTransform(CSng(location.X), CSng(location.Y))
                Me.actions.Item(i).Draw(e.Graphics)
                e.Graphics.EndContainer(container)
            Next i
            Return False
        End Function

        Private Sub Refresh()
            Dim parentView As WorkflowView = MyBase.ParentView
            Dim i As Integer
            For i = 0 To Me.actions.Count - 1
                parentView.InvalidateClientRectangle(Me.GetActionBounds(i))
            Next i
        End Sub

        Friend Sub RefreshAction(ByVal action As DynamicAction)
            If (action Is Nothing) Then
                Throw New ArgumentNullException("action")
            End If
            Dim index As Integer = Me.actions.IndexOf(action)
            If (index >= 0) Then
                MyBase.ParentView.InvalidateClientRectangle(Me.GetActionBounds(index))
            End If
        End Sub

        Friend Sub RemoveAction(ByVal action As DynamicAction)
            If (action Is Nothing) Then
                Throw New ArgumentNullException("action")
            End If
            If Me.actions.Contains(action) Then
                If Me.IsButtonDragged Then
                    Me.SetDraggedButton(-1, -1)
                End If
                Me.RefreshAction(action)
                Me.actions.Remove(action)
            End If
        End Sub

        Private Sub SetDraggedButton(ByVal actionIndex As Integer, ByVal buttonIndex As Integer)
            If ((Me.draggedActionIndex <> actionIndex) OrElse (Me.draggedButtonIndex <> buttonIndex)) Then
                Dim parentView As WorkflowView = MyBase.ParentView
                If ((Me.draggedActionIndex >= 0) AndAlso (Me.draggedButtonIndex >= 0)) Then
                    If (Me.draggedActionIndex < Me.actions.Count) Then
                        Me.actions.Item(Me.draggedActionIndex).Buttons.Item(Me.draggedButtonIndex).State = States.Highlight
                    End If
                    Me.draggedActionIndex = -1
                    Me.draggedButtonIndex = -1
                    parentView.Capture = False
                    Me.UpdateTransparency(parentView.PointToClient(Control.MousePosition))
                End If
                Me.draggedActionIndex = actionIndex
                Me.draggedButtonIndex = buttonIndex
                If ((Me.draggedActionIndex >= 0) AndAlso (Me.draggedButtonIndex >= 0)) Then
                    parentView.Capture = True
                End If
            End If
        End Sub

        Private Sub UpdateTransparency(ByVal point As Point)
            Dim i As Integer
            For i = 0 To Me.actions.Count - 1
                Dim num2 As Single = 0!
                If Not point.IsEmpty Then
                    Dim actionBounds As Rectangle = Me.GetActionBounds(i)
                    If (actionBounds.Contains(point) OrElse (Me.draggedActionIndex = i)) Then
                        num2 = 1!
                    Else
                        Dim viewPortRectangle As Rectangle = MyBase.ParentView.ViewPortRectangle
                        Dim num3 As Double = DesignerGeometryHelper.DistanceFromPointToRectangle(point, actionBounds)
                        If ((num3 > (viewPortRectangle.Width / 3)) OrElse (num3 > (viewPortRectangle.Height / 3))) Then
                            num2 = 0.3!
                        Else
                            num2 = 1!
                        End If
                    End If
                End If
                Me.actions.Item(i).Transparency = num2
            Next i
        End Sub


        ' Properties
        Private ReadOnly Property IsButtonDragged As Boolean
            Get
                Return ((Me.draggedActionIndex >= 0) AndAlso (Me.draggedButtonIndex >= 0))
            End Get
        End Property


        ' Fields
        Private actions As List([Of] DynamicAction) = New List([Of] DynamicAction)
        Private draggedActionIndex As Integer = -1
        Private draggedButtonIndex As Integer = -1
        Private infoTipSet As Boolean
    End Class
End Namespace

